#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <asm/io.h>

// GPIO1_4 红灯
// GPIO4_20 绿灯
// GPIO4_19 蓝灯

// GPIO1寄存器地址定义
#define GPIO1_DR  		(0x0209C000)  // 数据寄存器
#define GPIO1_DRIR  	(0x0209C004)  // 方向寄存器,0为输入，1为输出
#define GPIO1_PSR  		(0x0209C008)  // 状态寄存器
#define GPIO1_ICR1  	(0x0209C00C)  // 中断配制寄存器1
#define GPIO1_ICR2  	(0x0209C010)  // 中断配制寄存器2
#define GPIO1_ICRIMR    (0x0209C014)  // 中断掩码寄存器
#define GPIO1_ICRISR    (0x0209C018)  // 中断状态寄存器
#define GPIO1_EDGE_SEL  (0x0209C01C)  // 边缘选择寄存器，用以配制双边沿触发中断
// GPIO1_4掩码(PWM3.OUT)
#define GPIO1_4_MASK   (1 << 4)

// GPIO1_4引脚复用控制寄存器
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04 (0x20E0000 + 0x6C)
// GPIO1_4引脚复用模式为ATL5
#define ATL5 (5)
#define GPIO1_4_MUX_MODE  ATL5
// GPIO1_4引脚控制寄存器，配制电气属性，如上下拉等
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO04 (0x20E0000 + 0x2F8)
// GPIO1时钟控制寄存器
#define CCM_CCGR1 (0x20C4000 + 0x6C)
#define GPIO1_4_CLK_MASK  (3 << 26)


// GPIO4寄存器地址定义
#define GPIO4_DR  		(0x020A8000)  // 数据寄存器
#define GPIO4_DRIR  	(0x020A8004)  // 方向寄存器,0为输入，1为输出
#define GPIO4_PSR  		(0x020A8008)  // 状态寄存器
#define GPIO4_ICR1  	(0x020A800C)  // 中断配制寄存器1
#define GPIO4_ICR2  	(0x020A8010)  // 中断配制寄存器2
#define GPIO4_ICRIMR    (0x020A8014)  // 中断掩码寄存器
#define GPIO4_ICRISR    (0x020A8018)  // 中断状态寄存器
#define GPIO4_EDGE_SEL  (0x020A801C)  // 边缘选择寄存器，用以配制双边沿触发中断
// GPIO4_19掩码(PWM7.OUT)
#define GPIO4_19_MASK   (1 << 19)
// GPIO4_20掩码(PWM8.OUT)
#define GPIO4_20_MASK   (1 << 20)

// GPIO4_19(PWM7.OUT)引脚复用控制寄存器
#define IOMUXC_SW_MUX_CTL_PAD_CSI_VSYNC (0x20E0000 + 0x1DC)
// GPIO4_19(PWM7.OUT)引脚控制寄存器，配制电气属性，如上下拉等
#define IOMUXC_SW_PAD_CTL_PAD_CSI_VSYNC (0x20E0000 + 0x468)
// GPIO4_20(PWM8.OUT)引脚复用控制寄存器
#define IOMUXC_SW_MUX_CTL_PAD_CSI_HSYNC (0x20E0000 + 0x1E0)
// GPIO4_20(PWM8.OUT)引脚控制寄存器，配制电气属性，如上下拉等
#define IOMUXC_SW_PAD_CTL_PAD_CSI_HSYNC (0x20E0000 + 0x46C)

// GPIO4_19引脚和GPIO4_20复用模式为ATL5
#define ATL5 (5)
#define GPIO4_19_MUX_MODE  ATL5
#define GPIO4_20_MUX_MODE  ATL5

// GPIO4时钟控制寄存器
#define CCM_CCGR3  (0x20C4000 + 0x74)
#define GPIO4_19_CLK_MASK  (3 << 12)
#define GPIO4_20_CLK_MASK  (3 << 12)

// 添加__iomem标记，编译器会检查此地址，确保在io空间
struct led_ctl_pin
{
	unsigned int __iomem *dr_pin;
	unsigned int __iomem *drir_pin;
	unsigned int __iomem *mux_pin;
	unsigned int __iomem *ctl_pin;
	unsigned int __iomem *clk_pin;
};

// 设备结构体
struct my_led_dev {
	struct cdev cdev;  // 字符设备结构体
    struct led_ctl_pin r_pin; // 红色led引脚
    struct led_ctl_pin g_pin; // 绿色led引脚
    struct led_ctl_pin b_pin; // 蓝色led引脚
	dev_t devno;  // 设备号
	struct class* my_led_class;
	struct device* my_led_device;
    struct mutex mutex;  // 用于同步的互斥体
	unsigned int r_on_cnt; // 红色led亮的次数
	unsigned int g_on_cnt; // 红色led亮的次数
	unsigned int b_on_cnt; // 红色led亮的次数
};